/*
 * @Author: your name
 * @Date: 2021-10-04 19:37:47
 * @LastEditTime: 2021-10-05 18:56:35
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \diff\src\mysnabbdom\updataChildren.js
 */
import { patchVnode } from './patch';
import createElement from './createElement';
function getkey(node){
    let { sel,data,children,text,elm } = node;
    const key = node.data.key;
    return { sel,data,children,text,elm,key}
}
function sameVnode(node1,node2){
    return node1.data.key==node2.data.key&&node1.sel==node2.sel;
}

export default function updataChildren(parentElm,oldCh,newCh){
    // 进入Diff -- 效率快
    // 缓存
    let keyMap=null;
    // 新前
    let newStartIdx = 0;
    // 旧前
    let oldStartIdx = 0;
    // 新后
    let newEndIdx = newCh.length-1;
    // 旧后
    let oldEndIdx = oldCh.length-1;
    // 旧前节点
    let oldStartNode = oldCh[0];
    // 旧后节点
    let oldEndNode = oldCh[oldEndIdx];
    // 新前节点
    let newStartNode = newCh[0];
    // 新后节点
    let newEndNode = newCh[newEndIdx];
    
    while(newStartIdx<=newEndIdx && oldStartIdx<=oldEndIdx){
        //  进入diff 更新策略 四种模式计算删除，增加，更新
        //  首先不是判断四种模式

        if(oldStartNode==null || oldCh[oldStartIdx]==undefined){
                oldStartNode = oldCh[++oldStartIdx];
        }else if(oldEndNode==null  || oldCh[oldEndIdx]==undefined){
                oldEndNode = oldCh[--oldEndIdx]
        }else if(newStartNode==null || newCh[newStartIdx]==undefined){
                newStartNode = newCh[++newStartIdx]
        }else if(newEndNode==null || newCh[newStartIdx]==undefined){
                newEndNode = newCh[--newEndIdx];
        }
        // 四大更新策略主要负责 更新节点
        //  旧前与新前 
        if(sameVnode(oldStartNode,newStartNode)){
            console.log('命中1')
            patchVnode(oldStartNode,newStartNode);
            // // 新 旧指针都要下移动
            oldStartNode = oldCh[++oldStartIdx];
            newStartNode = newCh[++newStartIdx];
        //  新后与旧后 
         }else if(sameVnode(oldEndNode,newEndNode)){
            console.log('命中2')
            patchVnode(oldEndNode,newEndNode);
            // 新 旧指针都要上移动
            oldEndNode = oldCh[--oldEndIdx];
            newEndNode = newCh[--newEndIdx];
        //  新后与旧前 
         }else if(sameVnode(oldStartNode,newEndNode)){
            console.log('命中3') 
            // // 移动 新后（旧前） 指向的这个节点到老节点的 旧后的后面
            //  命中后将新后最后一个节点放到旧后的最后一个的后面 以此类推
            patchVnode(oldStartNode,newEndNode);
            parentElm.elm.insertBefore(oldStartNode.elm,oldEndNode.elm.nextSibling); 
            oldStartNode = oldCh[++oldStartIdx];
            newEndNode = newCh[--newEndIdx];
        //  新前与旧后
         }else if(sameVnode(oldEndNode,newStartNode)){
            console.log('命中4')
            // // 此时要移动新前到旧前的前面  移动 新前（旧后） 指向的这个节点到老节点的 旧前的前面 
            // 命中后将新前第一个节点 放到 旧后的第一个节点前面 依次类推
            patchVnode(oldEndNode,newStartNode);
            parentElm.elm.insertBefore(oldEndNode.elm,oldStartNode.elm);
            oldEndNode = oldCh[--oldEndIdx];
            newStartNode = newCh[++newStartIdx];
         }else{
            //  以上四种都没命中
            //  以下主要负责删除、增加
            if(!keyMap){
                 keyMap={};
                //  创建映射对象 通过key获取下标索引
                 for(let i = oldStartIdx;i<=oldEndIdx;i++){
                      const key = oldCh[i];
                      if(key != undefined){
                            keyMap[key.data.key]=i;
                      }
                 }
                 const oldIdIndex = keyMap[newStartNode.data.key];
                //  如果oldIdIndex为undfined 该项为新节点
                if(oldIdIndex==undefined){
                    //  被加入项
                    // newStartIdx++
                    parentElm.elm.insertBefore(createElement(newStartNode),oldStartNode.elm); 
                }else{
                    console.log(oldIdIndex)
                    // 如果不是undefined 标识节点需要移动
                    const oldElmMove = oldCh[oldIdIndex];
                      // 对比内容
                      patchVnode(oldElmMove,newStartNode);
                      // 插入
                      oldCh[oldIdIndex] = undefined;
                      parentElm.elm.insertBefore(oldElmMove.elm,oldStartNode.elm);
                }
                newStartNode = newCh[++newStartIdx];
            }    
         }
       
      
    }
    // 添加/删除
    if(newStartIdx<=newEndIdx){
        // 每当旧节点先遍历完 如果此层判断成立说明，剩下的新节点为新增节点
        console.log('有新节点')
        // 说明有新元素需要添加
         for(let i = newStartIdx;i<=newEndIdx;i++){
            //  将其添加到相应索引的前面
             parentElm.elm.insertBefore(createElement(newCh[i]),oldCh[oldStartIdx].elm);
         }
    }else if(oldStartIdx<=oldEndIdx){
        console.log('有多余节点');
        // // 说明有元素需要删除
        // 每当新节点先遍历完说明旧节点有删除的节点
        for(let i = oldStartIdx;i<=oldEndIdx;i++){
            if(oldCh[i]){
                parentElm.elm.removeChild(oldCh[i].elm);
            }
            
        }
    }
}